#pragma once 

#include "util.hpp"
#include <mutex>
#include <cassert>
class user_table{
private:
    std::mutex _mutex;//互斥锁保护数据库的访问操作
    MYSQL* _mysql;//mysql操作句柄

public:
    user_table(
        const std::string& host,
        const std::string& user,
        const std::string passwd,
        const std::string& db,int port){
            _mysql=mysql_util::mysql_create(host,user,passwd,db,port);
            if(_mysql==nullptr){
                ERR_LOG("msyql create failed!!!");
                assert(_mysql);
            }
        }
        //注册时新增用户
        bool insert(Json::Value &user){
            //初始分数给1000
#define INSERT_USER "insert into user value(null,'%s',MD5('%s'),1000,0,0);"
            if(user["username"].isNull() || user["password"].isNull() ){
                DBG_LOG("用户名和密码不完整！！");
                return false;
            }
            char sql[1024];
            sprintf(sql,INSERT_USER,user["username"].asCString(),user["password"].asCString());
            bool ret=mysql_util::mysql_exec(_mysql,sql);
            if(ret==false){
                DBG_LOG("insert user info failed!!");
                return false;
            }
            return true;
        }
        //登录验证，并返回详细的用户信息
        bool login(Json::Value & user){
            if(user["username"].isNull() || user["password"].isNull()){
                DBG_LOG("INPUT USERNAME OR PASSWORD");
                return false;
            }
#define LOGIN_USER "select id, score,total_count,win_count from user where username= '%s' and password=MD5('%s'); "
            char sql[1024];
            sprintf(sql,LOGIN_USER,user["username"].asCString(),user["password"].asCString());
            MYSQL_RES* res=nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                bool ret=mysql_util::mysql_exec(_mysql,sql);
                if(ret==false){
                    DBG_LOG("user login failed!!");
                    return false;
                }
                //按理来说，要么没数据，要么只有一条数据
                res=mysql_store_result(_mysql);
                if(res==nullptr){
                    DBG_LOG("no login info!!!");
                    return false;
                }
            }
            //行数不等于1的情况
            if(mysql_num_rows(res)!=1){
                DBG_LOG("the user information queried is not unique!!");
                return false;
            }
            //获取这一行数据
            MYSQL_ROW row=mysql_fetch_row(res);
            user["id"]=(Json::UInt64)std::stoi(row[0]);
            user["score"]=(Json::UInt64)std::stoi(row[1]);
            user["total_count"]=(Json::UInt64)std::stoi(row[2]);
            user["win_count"]=(Json::UInt64)std::stoi(row[3]);
            //释放结果集
            mysql_free_result(res);
            return true;
        }
        //通过用户名获取用户信息
        bool select_by_name(const std::string& name,Json::Value &user){
#define USER_BY_NAME "select id,score,total_count,win_count from user where username='%s';"
            char sql[1024];
            sprintf(sql,USER_BY_NAME,name.c_str());
            MYSQL_RES* res=nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                bool ret=mysql_util::mysql_exec(_mysql,sql);
                if(ret==false){
                    DBG_LOG("get user by name failed!!!");
                    return false;
                }
                res=mysql_store_result(_mysql);
                if(res==nullptr){
                    DBG_LOG("name:%s not in mysql",name.c_str());
                    return false;
                }
            }
            if(mysql_num_rows(res)!=1){
                DBG_LOG("the user information queried is not unique!!");
                return false;
            }
            //获取这一行数据
            MYSQL_ROW row=mysql_fetch_row(res);
            user["id"]=(Json::UInt64)std::stoi(row[0]);
            user["username"]=name;
            user["score"]=(Json::UInt64)std::stoi(row[1]);
            user["total_count"]=(Json::UInt64)std::stoi(row[2]);
            user["win_count"]=(Json::UInt64)std::stoi(row[3]);
            //释放结果集
            mysql_free_result(res);
            return true;
        }
        //通过ID获取用户信息
        bool select_by_id(const uint64_t id,Json::Value &user){
#define USER_BY_ID "select username,score,total_count,win_count from user where id=%d;"
            char sql[1024];
            sprintf(sql,USER_BY_ID,id);
            MYSQL_RES* res=nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                bool ret=mysql_util::mysql_exec(_mysql,sql);
                if(ret==false){
                    DBG_LOG("get user by name failed!!!");
                    return false;
                }
                res=mysql_store_result(_mysql);
                if(res==nullptr){
                    DBG_LOG("id: %d have no user info!!",id);
                    return false;
                }
            }
            if(mysql_num_rows(res)!=1){
                DBG_LOG("the user information queried is not unique!!");
                return false;
            }
            //获取这一行数据
            MYSQL_ROW row=mysql_fetch_row(res);
            user["id"]=(Json::UInt64)id;
            user["username"]=row[0];
            user["score"]=(Json::UInt64)std::stoi(row[1]);
            user["total_count"]=(Json::UInt64)std::stoi(row[2]);
            user["win_count"]=(Json::UInt64)std::stoi(row[3]);
            //释放结果集
            mysql_free_result(res);
            return true;
        }
        //胜利时天梯分数增加30，战斗场次增加1，胜利场次增加1
        bool win(uint64_t id){
#define USER_WIN "update user set score=score+30,total_count=total_count+1,win_count=win_count+1 where id=%d;"
            char sql[1024];
            sprintf(sql,USER_WIN,id);
            bool ret=mysql_util::mysql_exec(_mysql,sql);
            if(ret==false){
                DBG_LOG("update win user info failed!!!");
                return false;
            }
            return true;
        }
        //失败时天梯分数减少30，战斗场数增加1，其他不变
        bool lose(uint64_t id){
#define USER_LOSE "update user set score=score-30,total_count=total_count+1 where id=%d;"
            char sql[1024];
            sprintf(sql,USER_LOSE,id);
            bool ret=mysql_util::mysql_exec(_mysql,sql);
            if(ret==false){
                DBG_LOG("update lose user info failed!!!");
                return false;
            }
            return true;
        }

};